package oa.hleast.xswl.service.activity.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import oa.hleast.common.constant.ConfigKeyConstant;
import oa.hleast.common.utils.DateUtils;
import oa.hleast.common.web.exception.BizException;
import oa.hleast.xswl.common.config.AppProps;
import oa.hleast.xswl.common.constant.CommonConstant;
import oa.hleast.xswl.common.enums.ActivityTypeEnum;
import oa.hleast.xswl.mapper.activity.*;
import oa.hleast.xswl.pojo.domain.activity.*;
import oa.hleast.xswl.pojo.dto.UmsUserDto;
import oa.hleast.xswl.pojo.form.activity.ActivitySignUpForm;
import oa.hleast.xswl.pojo.vo.activity.ManagerUserSignUpVo;
import oa.hleast.xswl.pojo.vo.activity.ShowCommonActivityVo;
import oa.hleast.xswl.pojo.vo.activity.ShowUserSignInVo;
import oa.hleast.xswl.pojo.vo.activity.TodayCommonActivityVo;
import oa.hleast.xswl.service.ISysCommonConfigService;
import oa.hleast.xswl.service.ISysDictItemService;
import oa.hleast.xswl.service.IUmsUserService;
import oa.hleast.xswl.service.activity.ICmsActivityTypeService;
import oa.hleast.xswl.service.activity.ICmsUserSignInService;
import oa.hleast.xswl.service.activity.ICmsUserSignUpService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
@AllArgsConstructor
public class CmsActivitySignUpServiceImpl extends ServiceImpl<CmsUserSignUpMapper, CmsUserSignUp> implements ICmsUserSignUpService {

    private final CmsCommonActivityMapper cmsCommonActivityMapper;
    private final CmsActivityTemplateMapper templateMapper;
    private final CmsActivityCalendarMapper calendarMapper;
    private final CmsUserSignInMapper signInMapper;
    private final ICmsUserSignInService signInService;
    private final ICmsActivityTypeService typeService;
    private final CmsActivityManagerUserMapper managerUserMapper;
    private final AppProps appProps;
    private final ISysDictItemService dictItemService;
    private final IUmsUserService umsUserService;
private final ISysCommonConfigService commonConfigService;
    /**
     * 活动报名
     */
    @Override
    public boolean userSignUp(Long userId, ActivitySignUpForm form) {
        Long templateId = form.getTemplateId();
        String jsonData = form.getJsonData();

        CmsActivityTemplate activityTemplate = templateMapper.selectById(templateId);
        if (ObjectUtils.isEmpty(activityTemplate)) {
            log.info("报名活动模板为空 templateId = {}", templateId);
            throw new BizException("报名失败，请联系管理员");
        }
        log.info("activityTemplate = {}", activityTemplate);

        // 活动信息
        Long scenesId = activityTemplate.getScenesId();
        CmsCommonActivity commonActivity = cmsCommonActivityMapper.selectById(scenesId);
        Integer signInNum = commonActivity.getSignInNum();
        Integer maxSignUpNumber = commonActivity.getMaxSignUpNumber();

        // 检查是否重复报名
        if (checkRepeat(userId, scenesId)) {
            throw new BizException("您已经报名该活动了哦!");
        }

        // 检查活动是否已报满
        if (signInNum + 1 > maxSignUpNumber) {
            throw new BizException("报名人数已满,下次早点来哦!");
        }



        // 活动类报名
        String trainingId = "3";
        // TODO martin
//        commonActivityService.getByConfigKey(ConfigKeyConstant.ACTIVITY_TYPE_TRAINING_ID).getData().getValue();
        log.info("trainingId = {}", trainingId);
        Long activityTypeId = new Long(trainingId);
        if (!activityTemplate.getActivityTypeId().equals(activityTypeId)) {
            // 检查用户报名过并且进行中的活动是否超过2个
            if (checkUserSignUpNum(userId, activityTemplate.getActivityTypeId())) {
                throw new BizException("您报名的活动超过2个了,请先参加报名过的活动吧!");
            }

            CmsUserSignUp userSignUp = CmsUserSignUp.builder()
                    .userId(userId)
                    .scenesId(activityTemplate.getScenesId())
                    .activityTypeId(activityTemplate.getActivityTypeId())
                    .calendarId(0L)
                    .activityTemplateId(templateId)
                    .templateJsonData(jsonData)
                    .build();
            boolean save = this.save(userSignUp);

            // 更新活动的已报名人数
            cmsCommonActivityMapper.updateSingUpNumber(scenesId);


            return save;
        }

        // 检查用户报名过并且进行中的活动是否超过2个
        if (checkUserSignUpNum(userId, activityTemplate.getActivityTypeId())) {
            throw new BizException("您报名的培训超过2个了,请先参加报名过的培训吧!");
        }

        String calendarIds = form.getCalendarIds();
        String[] calendarIdList = calendarIds.split(",");

        List<CmsUserSignUp> userSignUpList = new ArrayList<>();
        for (String id : calendarIdList) {
            CmsUserSignUp userSignUp = CmsUserSignUp.builder()
                    .userId(userId)
                    .calendarId(new Long(id))
                    .scenesId(activityTemplate.getScenesId())
                    .activityTypeId(activityTemplate.getActivityTypeId())
                    .activityTemplateId(templateId)
                    .templateJsonData(jsonData)
                    .build();
            userSignUpList.add(userSignUp);

        }

        log.info("userSignUpList = {}", userSignUpList);
        boolean batchSave = this.saveBatch(userSignUpList);

        // 更新活动的已报名人数
        cmsCommonActivityMapper.updateSingUpNumber(scenesId);

        return batchSave;
    }

    private boolean checkRepeat(Long userId, Long scenesId) {
        Integer count = this.count(new LambdaQueryWrapper<CmsUserSignUp>()
                .eq(CmsUserSignUp::getUserId, userId)
                .eq(CmsUserSignUp::getScenesId, scenesId)
        );

        if (count > 0) {
            return true;
        }
        return false;
    }

    /**
     * 检查是否报名超过两人
     */
    private boolean checkUserSignUpNum(Long userId, Long activityTypeId) {

        List<CmsUserSignUp> list = this.list(new QueryWrapper<CmsUserSignUp>()
                .select("distinct scenes_id")
                .eq("user_id", userId)
                .eq("activity_type_id", activityTypeId));

        if (list.size() < 2) {
            return false;
        }
        // 检查活动是否已结束
        int signInNum = 0;

        for (CmsUserSignUp userSignUp : list) {
            Long scenesId = userSignUp.getScenesId();
            // 检查活动是否结束
            int count = calendarMapper.isActivityEnd(scenesId, new Date());
            if (count > 0) {
                signInNum += 1;
            }
        }

        if (signInNum >= 2) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 用户今天签到的培训活动列表
     */
    @Deprecated
    @Override
    public List<TodayCommonActivityVo> findUserActivity(Long userId) {

        String trainingId ="0";
        // TODO  martin
//        userFeignService.getByConfigKey(ConfigKeyConstant.ACTIVITY_TYPE_TRAINING_ID).getData().getValue();
        Long activityTypeId = new Long(trainingId);

        return findUserActivityList(userId, activityTypeId);
    }

    /**
     * 用户今天可签到的所有类型的活动列表
     */
    @Override
    public List<TodayCommonActivityVo> findAllUserActivity(Long userId) {

        return findUserActivityList(userId, null);
    }

    @Override
    public List<TodayCommonActivityVo> findUserActivityByCode(Long userId, String code) {
        CmsActivityType activityType = typeService.getByCode(code);

        return findUserActivityList(userId, activityType.getId());
    }

    @Override
    public boolean isSignUpByActivityId(Long activityId, Long userId) {

        int count = this.count(new LambdaQueryWrapper<CmsUserSignUp>()
                .eq(CmsUserSignUp::getScenesId, activityId)
                .eq(CmsUserSignUp::getUserId, userId)
                .last("limit 1")
        );

        if (count > 0) {
            return true;
        }
        return false;
    }

    @Override
    public List<TodayCommonActivityVo> findUserVenue(Long userId) {
        log.info("userId = {}", userId);
        String value = commonConfigService.getByConfigKey(ConfigKeyConstant.ACTIVITY_VENUE_CODE_LIST).getValue();
        List<String> codeList = Arrays.asList(value.split(","));
        if (CollectionUtils.isEmpty(codeList)) {
            throw new BizException("系统异常");
        }

        List<Long> activityTypeIdList = codeList.stream().map(code -> {
            CmsActivityType activityType = typeService.getByCode(code);
            return activityType.getId();
        }).collect(Collectors.toList());
        log.info("findUserVenue,activityTypeIdList = {}", activityTypeIdList);

        LambdaQueryWrapper<CmsUserSignUp> queryWrapper = new LambdaQueryWrapper<CmsUserSignUp>().eq(CmsUserSignUp::getUserId, userId).orderByDesc(CmsUserSignUp::getGmtCreate);
        queryWrapper.in(CmsUserSignUp::getActivityTypeId, activityTypeIdList);
        List<CmsUserSignUp> list = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            log.info("没有报名活动 userId = {}", userId);
            return new ArrayList<>();
        }
        log.info("findUserVenue,list = {}", list);

        // 签到时间 取当天4点到10点
        Date beginOfDay = DateUtils.beginOfDay(new Date());
        DateTime startDateTime = DateUtils.offsetHour(beginOfDay, 4);
        DateTime endDateTime = DateUtils.offsetHour(beginOfDay, 22);

        List<TodayCommonActivityVo> voList = new ArrayList<>();
        for (CmsUserSignUp userSignUp : list) {
            CmsCommonActivity commonActivity = cmsCommonActivityMapper.selectById(userSignUp.getScenesId());
            TodayCommonActivityVo vo = conversionToTodayVo(commonActivity);
            vo.setSignIn(isUserActivitySignIn(userId, userSignUp.getScenesId()));
            // 添加 可签到的开始时间与结束时间
            vo.setSignInStartDate(startDateTime);
            vo.setSignInEndDate(endDateTime);
            voList.add(vo);
        }

        log.info("findUserVenue, voList = {}", voList);

        return voList;
    }

    private List<TodayCommonActivityVo> findUserActivityList(Long userId, Long activityTypeId) {
        // 获取用户报名的所有培训类型的活动
        LambdaQueryWrapper<CmsUserSignUp> queryWrapper = new LambdaQueryWrapper<CmsUserSignUp>().eq(CmsUserSignUp::getUserId, userId).orderByDesc(CmsUserSignUp::getGmtCreate);
        if (ObjectUtils.isNotEmpty(activityTypeId)) {
            queryWrapper.eq(CmsUserSignUp::getActivityTypeId, activityTypeId);
        }

        List<CmsUserSignUp> list = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            log.info("没有报名活动 userId = {}", userId);
            return null;
        }
        // 报名活动的集合
        List<Long> activityIds = list.stream().map(CmsUserSignUp::getScenesId).collect(Collectors.toList());

        log.info("activityIds = {}", activityIds);
        //获取用户报名的培训活动的具体信息
        List<CmsCommonActivity> commonActivityList = cmsCommonActivityMapper.selectBatchIds(activityIds);
        log.info("commonActivityList = {}", commonActivityList);

        //匹配活动
        // 获取今天的年月日
        LocalDate today = LocalDate.now();
        int year = today.getYear();
        int month = today.getMonthValue();
        int day = today.getDayOfMonth();

        List<TodayCommonActivityVo> voList = new ArrayList<>();
        for (CmsCommonActivity commonActivity : commonActivityList) {
            List<CmsActivityCalendar> calendarList = calendarMapper.selectList(new LambdaQueryWrapper<CmsActivityCalendar>()
                    .eq(CmsActivityCalendar::getActivityId, commonActivity.getId())
                    .eq(CmsActivityCalendar::getYear, year)
                    .eq(CmsActivityCalendar::getMonth, month)
                    .eq(CmsActivityCalendar::getDay, day));

            log.info("calendarList = {}", calendarList);

            for (CmsActivityCalendar calendar : calendarList) {
                TodayCommonActivityVo vo = conversionToTodayVo(commonActivity);
                vo.setCalenderId(calendar.getId());
                vo.setSignIn(signInService.isSignInByCalendarAndUserId(userId, calendar.getId()));
                // 添加 可签到的开始时间与结束时间
                vo.setSignInStartDate(getSignInStartDate(calendar));
                vo.setSignInEndDate(getSIgnInEndDate(calendar));
                voList.add(vo);
            }
        }
        log.info("voList = {}", voList);

        return voList;
    }


    @Override
    public List<CmsUserSignUp> findUserByCalendarId(Long calendarId) {
        List<CmsUserSignUp> list = this.list(new LambdaQueryWrapper<CmsUserSignUp>().eq(CmsUserSignUp::getCalendarId, calendarId));
        log.info("list = {}", list);
        return list;
    }

    @Override
    public List<ShowUserSignInVo> findUserSignInByForCalendar(Long calendarId) {
        // 所有报名的人
        List<CmsUserSignUp> list = this.list(new LambdaQueryWrapper<CmsUserSignUp>().eq(CmsUserSignUp::getCalendarId, calendarId));

        // 匹配签到情况
        List<ShowUserSignInVo> voList = list.stream().map(pojo -> {
            ShowUserSignInVo vo = new ShowUserSignInVo();
            BeanUtil.copyProperties(pojo, vo);
            vo.setUserSignUpId(pojo.getId());

            List<CmsUserSignIn> signInList = signInMapper.selectList(new LambdaQueryWrapper<CmsUserSignIn>()
                    .eq(CmsUserSignIn::getUserId, pojo.getUserId())
                    .eq(CmsUserSignIn::getCalendarId, pojo.getCalendarId())
                    .last("limit 1")
            );
            if (CollectionUtils.isNotEmpty(signInList)) {
                CmsUserSignIn userSignIn = signInList.get(0);
                vo.setASignIn(true);
                vo.setBodyTemperature(userSignIn.getBodyTemperature());
                vo.setSignInDate(userSignIn.getSignInDate());
                vo.setUserSignInId(userSignIn.getId());
                vo.setSignInDate(userSignIn.getSignInDate());
            }

            // 添加姓名
            UmsUserDto umsUserDto = umsUserService.getUserDtoById(pojo.getUserId());
//            MemberDTO memberDTO = umsUserService.getUserById(pojo.getUserId()).getData();
            vo.setUserName(umsUserDto.getNickname());

            return vo;
        }).collect(Collectors.toList());

        return voList;
    }

    @Override
    public Integer countSignUpByCalendar(Long calendarId) {

        return this.count(new LambdaQueryWrapper<CmsUserSignUp>()
                .eq(CmsUserSignUp::getCalendarId, calendarId)
        );
    }

    @Override
    public boolean isSignUpByCalendar(Long calendarId, Long userId) {
        int count = this.count(new LambdaQueryWrapper<CmsUserSignUp>()
                .eq(CmsUserSignUp::getCalendarId, calendarId)
                .eq(CmsUserSignUp::getUserId, userId)
                .last("limit 1")
        );

        if (count > 0) {
            return true;
        }
        return false;
    }

    /**
     * 更新体温
     *
     * @param signInId
     * @param bodyTemperature
     */
    @Override
    public Boolean updateBodyTemperature(Long signInId, String bodyTemperature) {
        CmsUserSignIn userSignIn = signInMapper.selectById(signInId);
        if (ObjectUtils.isEmpty(userSignIn)) {
            log.info("signInId = {}", signInId);
            throw new BizException("数据异常");
        }

        userSignIn.setBodyTemperature(bodyTemperature);
        int i = signInMapper.updateById(userSignIn);
        if (i == 1) {
            return true;
        }
        return false;
    }

    /**
     * 某活动的用户报名情况
     *
     * @param activityId 活动ID
     */
    @Override
    public Page<ManagerUserSignUpVo> findUserSignUpByForActivityId(Long activityId, Integer page, Integer limit) {
        Page<CmsUserSignUp> pojoPage = this.page(new Page<>(), new QueryWrapper<CmsUserSignUp>()
                .select("distinct user_id,template_json_data,activity_template_id,review_status")
                .eq("scenes_id", activityId));

        if (ObjectUtils.isEmpty(pojoPage) || pojoPage.getTotal() == 0) {
            return new Page<>(page, limit, 0);

        }
        List<ManagerUserSignUpVo> voList = pojoPage.getRecords().stream().map(pojo -> {
            ManagerUserSignUpVo vo = conversionToSignUpVo(pojo);
            // 添加报名姓名

            UmsUserDto userDto = umsUserService.getUserDtoById(pojo.getUserId());
//                    memberFeignService.getUserDtoById(pojo.getUserId()).getData();
            vo.setUsername(userDto.getNickname());
            vo.setFullName(userDto.getFullname());
            vo.setIdCard(userDto.getIdCardNum());
            vo.setMobile(userDto.getMobile());
            vo.setScenesId(activityId);

            return vo;
        }).collect(Collectors.toList());
        Page<ManagerUserSignUpVo> voPage = new Page<>(page, limit, pojoPage.getTotal());
        voPage.setRecords(voList);
        log.info("voList = {}", voList);
        return voPage;
    }


    private ManagerUserSignUpVo conversionToSignUpVo(CmsUserSignUp pojo) {
        ManagerUserSignUpVo vo = new ManagerUserSignUpVo();
        BeanUtil.copyProperties(pojo, vo);
        return vo;
    }


    private TodayCommonActivityVo conversionToTodayVo(CmsCommonActivity pojo) {
        TodayCommonActivityVo vo = new TodayCommonActivityVo();
        BeanUtil.copyProperties(pojo, vo);

        // 转换活动类型 后期优化
        CmsActivityType activityType = typeService.getById(pojo.getActivityTypeId());
        if (ObjectUtils.isNotEmpty(activityType)) {
            vo.setActivityTypeName(activityType.getName());
        } else {
            vo.setActivityTypeName("活动");
        }

        return vo;
    }

    @Override
    public boolean add(CmsUserSignUp form) {
        return this.save(form);
    }

    @Override
    public boolean update(CmsUserSignUp form) {
        return this.update(form);
    }

    @Override
    public Page<CmsUserSignUp> pageList(Integer page, Integer limit, String typeName, Integer display) {
        return this.page(new Page<>(page, limit), new LambdaQueryWrapper<CmsUserSignUp>()
                .orderByDesc(CmsUserSignUp::getGmtCreate)
                .orderByDesc(CmsUserSignUp::getGmtModified)
        );
    }

    @Override
    public boolean deleteByIds(List<String> asList) {
        return this.removeByIds(asList);
    }

    @Override
    public CmsUserSignUp detail(Long id) {
        return this.getById(id);
    }

    private ShowCommonActivityVo conversion(CmsCommonActivity pojo) {
        ShowCommonActivityVo vo = new ShowCommonActivityVo();
        BeanUtil.copyProperties(pojo, vo);
        return vo;
    }

    private Long getActivityTypeId(ActivityTypeEnum enumByCode) {
        Long activityTypeId = null;
        switch (enumByCode) {
            case ALL:
                break;
            case TRAINING:
                String trainingId = commonConfigService.getByConfigKey(ConfigKeyConstant.ACTIVITY_TYPE_TRAINING_ID).getValue();

                activityTypeId = new Long(trainingId);
                break;
            default:
                activityTypeId = null;
        }
        return activityTypeId;
    }

    /**
     * 签到结束时间
     */
    @Override
    public Date getSIgnInEndDate(CmsActivityCalendar calendar) {
        return calendar.getActivityEndDate();
    }

    /**
     * 签到开始时间
     */
    @Override
    public Date getSignInStartDate(CmsActivityCalendar calendar) {
        return new Date(calendar.getActivityStartDate().getTime() - CommonConstant.MINUTE_LONG_30);
    }

    @Override
    public Boolean activityReview(Long scenesId, String review,Long signUpUserId) {
        int count = this.count(new LambdaQueryWrapper<CmsUserSignUp>()
                .eq(CmsUserSignUp::getScenesId, scenesId)
        );
        if(count <= 0){
            throw new BizException("数据不存在");
        }
        boolean update = this.update(new LambdaUpdateWrapper<CmsUserSignUp>()
                .set(CmsUserSignUp::getReviewStatus,review)
                .eq(CmsUserSignUp::getScenesId,scenesId)
                .eq(CmsUserSignUp::getUserId,signUpUserId)
        );
        return update;
    }

    @Override
    public Boolean activityCancel(Long scenesId, Long signUpUserId) {
        int count = this.count(new LambdaQueryWrapper<CmsUserSignUp>()
                .eq(CmsUserSignUp::getScenesId, scenesId)
        );
        if(count <= 0){
            throw new BizException("数据不存在");
        }
        boolean update = this.update(new LambdaUpdateWrapper<CmsUserSignUp>()
                .set(CmsUserSignUp::getDeleted,1)
                .eq(CmsUserSignUp::getScenesId,scenesId)
                .eq(CmsUserSignUp::getUserId,signUpUserId)
        );
        return update;
    }

    public Boolean isUserActivitySignIn(Long studentUserId, Long activityId) {

        int count = signInMapper.countToDayActivityId(studentUserId, activityId);
        if (count > 0) {
            return true;
        }
        return false;
    }
}
